package logger

import (
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"io"
	"os"
	"time"
)

var (
	logger *zap.Logger
)

//init 初始化logger
func init() {

	encoder := zapcore.NewConsoleEncoder(zapcore.EncoderConfig{
		MessageKey:  "msg",
		LevelKey:    "level",
		EncodeLevel: zapcore.CapitalLevelEncoder,
		TimeKey:     "ts",
		EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
			enc.AppendString(t.Format("2006-01-02 15:04:05"))
		},
		CallerKey:    "file",
		EncodeCaller: zapcore.ShortCallerEncoder,
		EncodeDuration: func(d time.Duration, enc zapcore.PrimitiveArrayEncoder) {
			enc.AppendInt64(int64(d) / 1000000)
		},
	})

	// Implement two interfaces to judge the log level (in fact, zapcore.*Level itself is the interface)
	infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl < zapcore.WarnLevel
	})

	warnLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl >= zapcore.WarnLevel
	})

	// Get io.Writer Abstract getWriter() of info and warn log files and implement it below
	infoWriter := getWriter("info")
	warnWriter := getWriter("warn")

	// Finally, create a specific Logger
	core := zapcore.NewTee(
		zapcore.NewCore(encoder, zapcore.AddSync(infoWriter), infoLevel),
		zapcore.NewCore(encoder, zapcore.Lock(os.Stdout), infoLevel),
		zapcore.NewCore(encoder, zapcore.AddSync(warnWriter), warnLevel),
		zapcore.NewCore(encoder, zapcore.Lock(os.Stderr), warnLevel),
	)

	logger = zap.New(core, zap.AddCaller())
}

func GetLogger() *zap.Logger {
	return logger
}

func getWriter(level string) io.Writer {
	fileName := "/tmp/logs/" + os.Args[0]
	// The actual file name generated by the Logger generating rotatelogs is demo.log.YYmmddHH
	// os.Args[0].log is a link to the latest log
	// Save the logs within 7 days, and split the logs every day (whole point)
	hook, err := rotatelogs.New(
		fileName+".%Y%m%d%H."+level, // No go style anti human format
		rotatelogs.WithLinkName(fileName),
		rotatelogs.WithMaxAge(time.Hour*24*7),
		rotatelogs.WithRotationTime(time.Hour*24),
	)

	if err != nil {
		panic(err)
	}
	return hook
}
